#include "jugador.h"

/** Con el constructor de jugador al crear el objeto lo situamos en la posición que queramos (X,Y)
 * e inicializamos el socket en la dirección y puerto de escucha correspondiente (se encarga el socket)
 * posteriormente recibimos la información inicial del servidor y se la pasamos a la función interpretar
 * y así podremos actuar en consecuencia en el main
*/

/**
 * @brief checkAngulo Comprobamos que el ángulo es correcto.
 * @param _angulo Valor del ángulo a comprobar.
 * @return Devuelve el valor del ángulo comprobado y corregido en caso de que fuese erróneo.
 */
float checkAngulo(float _angulo)
{
    float angulo = _angulo;
    if (angulo < -180) angulo = -180;
    if (angulo > 180)  angulo = 180;
    return angulo;
}

/**
 * @brief checkPotencia Comprobamos que la potencia es correcta.
 * @param _potencia Valor de la potencia a comprobar.
 * @return Devuelve el valor de la potencia comprobada y corregida en caso de que fuese errónea.
 */
float checkPotencia(float _potencia)
{
    float potencia = _potencia;
    if (potencia < -100)  potencia = -100;
    if (potencia > 100)   potencia = 100;
    return potencia;
}

/**
 * @brief Jugador::Jugador Constructor neceseario para la realización de los tests.
 */
Jugador::Jugador(){ veoPelota=false;}

/**
 * @brief Jugador::Jugador Constructor de nuestro jugador.
 * @param argc Número de parametros que tiene la cadena que pasamos por valor.
 * @param argv Array donde se almacenan los parámetros. Los parametros son la dirección del servidor
 * y el puerto.
 */
Jugador::Jugador(int argc, char *argv[])
{
    cicloGolpeo = 0;
    te = clock();
    tr = clock();
    thread_flag=false;
    veoPelota=false;
    pthread_mutex_init (&this->_mutex, (pthread_mutexattr_t*) NULL);
    cliente.checkConnection(argc);
    cliente.socket(argv);
    recibir.start(this);
    sleep(0.5);
    cliente.enviar("(init Grupo_3)");
    thread_flag = false;
    sleep(2);
    thread_flag = false;
    numero = datos.getNumero();
    cout << "Jugador con el dorsal " << numero << " juega en el lado " << datos.getSide() << endl;
}


/**
 * @brief Jugador::setnumero Introducimos el dorsal al jugador.
 * @param Nnumero Número de dorsal.
 */
void Jugador::setnumero(int Nnumero)
{
    numero = Nnumero;
}
/**
 * @brief Jugador::getnumero
 * @return Devolvemos el número del jugador.
 * @see
 */
int Jugador::getnumero()
{
    return numero;
}

/**
 * @brief Jugador::setalpha Asignamos valor al ángulo del jugador.
 * @param num Valor a asignar.
 */
void Jugador::setalpha(double num)
{
    alpha=num;
}

/**
 * @brief Jugador::getalpha
 * @return Devolvemos el ángulo del jugador.
 */
double Jugador::getalpha()
{
    return alpha;
}
/**
 * @brief Jugador::comprobar_pelota Comprobamos si el jugador ve la pelota.
 * @param h Cadena recibida desde el servidor.
 */
void Jugador::comprobar_pelota(string h)
{
    if (h.find("see")!=string::npos && h.find("ball")!=string::npos)
        veoPelota=true;
    else
        if (h.find("see")!=string::npos && h.find("ball")==string::npos)
            veoPelota=false;
}

/**
 * @brief Jugador::posicionPorteria Calculamos la dirección de la portería con respecto a nuestro jugador.
 */
void Jugador::posicionPorteria()
{
    int goal_x,goal_y,angle;
    if(datos.getSide() == "l")
        goal_x = 52.5;
    else
        goal_x = -52.5;
    goal_y = 0;
    distPorteria = sqrt (pow(goal_x-posicion.getX(),2)+pow(posicion.getY(),2));
    angle = acos((goal_x-posicion.getX())/distPorteria)*180/3.141592;
    if (posicion.getY()<0)
        angle = 360 - angle;

    dirPorteria = (alpha - angle);
    if (dirPorteria < 0)
        dirPorteria += 360;
    if (dirPorteria>180)
        dirPorteria -= 360;

}

/**
 * @brief Jugador::posicionPelota Calculamos la posición absoluta de la pelota en el campo.
 * @return Devolvemos la posición de la pelota.
 */
Punto Jugador::posicionPelota()
{
    double x,y,angle;
    Punto pos;
    angle = alpha - datos.getSeeInst("ball").getDir() ;
    x = posicion.getX()+ (datos.getSeeInst("ball").getDist()*cos(angle));
    y = posicion.getY()+ (datos.getSeeInst("ball").getDist()*sin(angle));
    pos.setX(x);
    pos.setY(y);
    return pos;
}

/**
 * @brief Jugador::interpretar Interpretamos los datos recibidos desde el servidor.
 * @param h Cadena que vamos a interpretar enviada por el servidor.
 */

void Jugador::interpretar(string h)
{
    parser.separardatos(h,datos);
    comprobar_pelota(h);
    setPosicion(h);
    posicionPorteria();
    hearReferee();
}

/**
 * @brief Jugador::golpear Función para golpear la pelota.
 * @param pot Potencia con la que golpear la pelota.
 * @param dir Dirección en la que queremos mandar la pelota.
 * @return Si las condiciones para golpear la pelota han sido favorables la función devuelve TRUE.
 */
bool Jugador::golpear(float pot, float dir)
{
    msg.str("");
    float potencia = checkPotencia(pot);
    float direccion = checkAngulo(dir);
    if (cicloGolpeo == datos.getCiclo()) //Evitamos golpear 2 veces en el mismo ciclo
        return false;
    else
        if (veoPelota && 0 < datos.getSeeInst("ball").getDist() && datos.getSeeInst("ball").getDist() < 0.7)
        {
            cout<<"Golpeo con una potencia: "<<potencia<<endl;
            msg << "(kick " << potencia << " " << direccion << ")";
            usleep(15000);
            cicloGolpeo = datos.getCiclo();
            return true;
        }
        else
            return false;
}

/**
 * @brief Jugador::mover Función para mover a nuestro jugador.
 * @param pot Potencia con la que aceleramos al jugador.
 */
void Jugador::mover(float pot)
{
    float potencia = checkPotencia(pot);
    msg.str(""); //BORRAMOS EL CONTENIDO PORQUE SI NO SE AÑADE AL FINAL
    msg<<"(dash "<<potencia<<")";

}

/**
 * @brief Jugador::girar Función para girar el cuerpo de nuestro jugador.
 * @param ang Ángulo que va a girar el jugador.
 *
 * Según el manual de la RoboCup el parámetro del comando "turn" no es un ángulo como
 * tal sino un momento que se calcula en función de parametros dados por el servidor.
 */
void Jugador::girar(float ang) //VA EN FUNCION DEL MOMENTO. LE PASAMOS EL ANGULO QUE QUEREMOS GIRAR
{
    double momento;
    momento=ang*(1.0+5*(datos.getSenseInst("speed").getValue1()));
    msg.str("");
    momento = checkAngulo(momento);
    msg<<"(turn "<<momento<<")";
}

/**
 * @brief Jugador::mirar Función para girar la cabeza de nuestro jugador.
 * @param ang Ángulo que giramos la cabeza del jugador.
 */
void Jugador::mirar(float ang)
{
    float angulo = checkAngulo(ang);
    msg.str("");
    msg<<"(turn_neck "<<angulo<<")";
}

/**
 * @brief Jugador::colocar Función para colocar nuestros jugadores por el campo al inicio del partido.
 * @param x Coordenada X de la posición del jugador.
 * @param y Coordenada Y de la posición del jugador.
 */
void Jugador::colocar(double x, double y)
{
    msg.str("");
    if(x<(-52.5) || x>(52.5))
        cout<<"Imposible colocar el jugador, coordenada X incorrecta"<<endl;
    if(y<-34 || y>34)
        cout<<"Imposible colocar el jugador, coordenada Y incorrecta"<<endl;
    msg<<"(move "<<x<<" "<<y<<")";
    pos_inicial.setX(x);
    pos_inicial.setY(y);
}

/**
 * @brief Jugador::buscarPelota Función para buscar la pelota y poner al jugador mirando hacia él.
 * @return La funcion buscar pelota devuelve FALSE si no esta viéndola y TRUE si la ve
 */
bool Jugador::buscarPelota()
{
    if (veoPelota)
    {
        if (-5 < datos.getSeeInst("ball").getDir() && datos.getSeeInst("ball").getDir() < 5)
            return true;
        else
        {
            //girar (datos.getSeeInst("ball").getDir());
            if (datos.getSeeInst("ball").getDir()<0)
            {
                girar (-5);
                usleep(15000);
            }
            else
            {
                girar (5);
                usleep(15000);
            }
        }
        return true;
    }

    else
    {
        girar(20);
        usleep(15000);
        return false;
    }
}

/**
 * @brief Jugador::seguirPelota Función para perseguir la pelota si ésta está dentro de la zona de juego del jugador
 * y golpearla cuando se de el caso.
 * @param zonaBalon Booleano que dicta si la pelota está dentro de la zona o no.
 */
void Jugador::seguirPelota (bool zonaBalon)
{
    if (buscarPelota() == true && zonaBalon == true && jugadorPropioCercaBalon() == false)
    {
        double velocidad = datos.getSeeInst("ball").getDist()*20;
        mover(velocidad);
        usleep(15000);
    }

    if (golpear(14*sqrt(distPorteria),dirPorteria))
        usleep(15000);
}

/**
 * @brief Jugador::seguirPelota Función para perseguir la pelota esté donde esté y golpearla cuando se de el caso.
 */
void Jugador::seguirPelota ()
{
    if (buscarPelota())
    {
        double velocidad = datos.getSeeInst("ball").getDist()*10;
        mover(velocidad);
        usleep(15000);
    }
    if (golpear(14*sqrt(distPorteria),dirPorteria))
        usleep(15000);
}

/**
 * @brief Jugador::correr Función para correr con la pelota dando pequeños golpes.
 *
 * En esta primera versión no se utiliza.
 */
void Jugador::correr()
{
    if (buscarPelota())
    {
        if(golpear(20,dirPorteria))
            usleep(15000);
        else
            mover(70);
        usleep(15000);
    }
}

/**
 * @brief Jugador::buscarIndicador Función para buscar algún indicador de la cadena See y mirar hacia él.
 * @param indicador Nombre del indicador que queremos buscar.
 */
void Jugador :: buscarIndicador(string indicador)
{
    while (true)
    {
        if(cliente.getSbuffer().find("see")!=string::npos && cliente.getSbuffer().find(indicador)!=string::npos)
        {
            while (5 < datos.getSeeInst(indicador).getDir() < -5)
            {
                girar(datos.getSeeInst(indicador).getDir());
                usleep(15000);
            }
            break;
        }
        else
        {
            girar(20);
            usleep(15000);
        }
    }

}

/**
 * @brief Jugador::esperarInicio Todos los jugadores menos uno esperan a que éste saque de centro del campo.
 */
void Jugador::esperarInicio()
{
    switch (numero)
    {
    case 2:
        pos_play.setX(-35);
        pos_play.setY(20);
        if(datos.getSide() == "r")
        {
            pos_play.setX(pos_play.getX()*(-1));
            pos_play.setY(pos_play.getY()*(-1));
        }
        break;
    case 3:
        pos_play.setX(pos_inicial.getX());
        pos_play.setY(pos_inicial.getY());
        break;
    case 4:
        pos_play.setX(pos_inicial.getX());
        pos_play.setY(pos_inicial.getY());
        break;
    case 5:
        pos_play.setX(-35);
        pos_play.setY(-20);
        if(datos.getSide() == "r")
        {
            pos_play.setX(pos_play.getX()*(-1));
            pos_play.setY(pos_play.getY()*(-1));
        }
        break;
    case 6:
        pos_play.setX(0);
        pos_play.setY(pos_inicial.getY());
        break;
    case 7:
        pos_play.setX(0);
        pos_play.setY(pos_inicial.getY());
        break;
    case 8:
        pos_play.setX(0);
        pos_play.setY(pos_inicial.getY());
        break;
    case 9:
        pos_play.setX(0);
        pos_play.setY(pos_inicial.getY());
        break;
    case 11:
        pos_play.setX(25);
        pos_play.setY(15);
        if(datos.getSide() == "r")
        {
            pos_play.setX(pos_play.getX()*(-1));
            pos_play.setY(pos_play.getY()*(-1));
        }
        break;
    case 10:
        pos_play.setX(25);
        pos_play.setY(-15);
        if(datos.getSide() == "r")
        {
            pos_play.setX(pos_play.getX()*(-1));
            pos_play.setY(pos_play.getY()*(-1));
        }
        break;
    }

    while(datos.getHearInst("referee").getinstruction() != "kick_off")
    {
        thread_flag = false;
        usleep(15000);
    }
    cout<<"Posición vista por el programa: ";
    posicion.printPunto();
    cout<<endl;
    enviar.start(this);
}

/**
 * @brief Jugador::setPosicion Calculamos la posición absoluta de nuestro jugador en el campo en coordenadas cartesianas.
 * @param h Cadena recibida desde el servidor de dónde sacamos la información.
 */
void Jugador::setPosicion(string h)
{

    double linedir,linedist, flagdir,flagdist=200,flag_x,flag_y,abs_x,abs_y, alpha2;
    if(h.find("see")!=string::npos)
    {
        if (h.find("(line r)")!=string::npos)
        {
            linedist = datos.getSeeInst("line r").getDist();
            linedir = 90  + datos.getSeeInst("line r").getDir();

            if (datos.getSeeInst("line r").getDir()>0)

                linedir = 270 + datos.getSeeInst("line r").getDir();
        }

        if (h.find("(line l)")!=string::npos)
        {
            linedist = datos.getSeeInst("line l").getDist();
            linedir = 90  + datos.getSeeInst("line l").getDir();

            if (datos.getSeeInst("line l").getDir()<0)

                linedir = 270  + datos.getSeeInst("line l").getDir();
        }

        if (h.find("(line t)")!=string::npos)
        {
            linedist = datos.getSeeInst("line t").getDist();
            linedir = datos.getSeeInst("line t").getDir();

            if (datos.getSeeInst("line t").getDir()<0)

                linedir = 180 + datos.getSeeInst("line t").getDir();
        }

        if (h.find("(line b)")!=string::npos)
        {
            linedist = datos.getSeeInst("line b").getDist();
            linedir = 180 + datos.getSeeInst("line b").getDir();

            if (datos.getSeeInst("line b").getDir()<0)

                linedir = 360 + datos.getSeeInst("line b").getDir();
        }

        if (h.find("flag")!=string::npos)
        {
            if (h.find("(flag l b)")!=string::npos)
            {
                if(flagdist>datos.getSeeInst("flag l b").getDist())
                {
                    flagdir= this->datos.getSeeInst("flag l b").getDir();
                    flagdist=this->datos.getSeeInst("flag l b").getDist();
                    flag_x=-52.5;
                    flag_y=34;
                }
            }
            if (h.find("(flag l t)")!=string::npos)
            {
                if(flagdist>datos.getSeeInst("flag l t").getDist())
                {
                    flagdir= this->datos.getSeeInst("flag l t").getDir();
                    flagdist=this->datos.getSeeInst("flag l t").getDist();
                    flag_x=-52.5;
                    flag_y=-34;
                }
            }
            if (h.find("(flag c t)")!=string::npos)
            {
                if(flagdist>datos.getSeeInst("flag c t").getDist())
                {
                    flagdir= this->datos.getSeeInst("flag c t").getDir();
                    flagdist=this->datos.getSeeInst("flag c t").getDist();
                    flag_x=0;
                    flag_y=-34;
                }
            }
            if (h.find("(flag r t)")!=string::npos)
            {
                if(flagdist>datos.getSeeInst("flag r t").getDist())
                {
                    flagdir= this->datos.getSeeInst("flag r t").getDir();
                    flagdist=this->datos.getSeeInst("flag r t").getDist();
                    flag_x=52.5;
                    flag_y=-34;
                }
            }
            if (h.find("(flag r b)")!=string::npos)
            {
                if(flagdist>datos.getSeeInst("flag r b").getDist())
                {
                    flagdir= this->datos.getSeeInst("flag r b").getDir();
                    flagdist=this->datos.getSeeInst("flag r b").getDist();
                    flag_x=52.5;
                    flag_y=34;
                }
            }
            if (h.find("(flag c b)")!=string::npos)
            {
                if(flagdist>datos.getSeeInst("flag c b").getDist())
                {
                    flagdir= this->datos.getSeeInst("flag c b").getDir();
                    flagdist= this->datos.getSeeInst("flag c b").getDist();
                    flag_x=0;
                    flag_y=34;
                }
            }
            if (h.find("(goal l)")!=string::npos)
            {
                if(flagdist>datos.getSeeInst("goal l").getDist())
                {
                    flagdir= this->datos.getSeeInst("goal l").getDir();
                    flagdist=this->datos.getSeeInst("goal l").getDist();
                    flag_x=-52.5;
                    flag_y=0;
                }
            }
            if (h.find("(goal r)")!=string::npos)
            {
                if(flagdist>datos.getSeeInst("goal r").getDist())
                {
                    flagdir= this->datos.getSeeInst("goal r").getDir();
                    flagdist=this->datos.getSeeInst("goal r").getDist();
                    flag_x=52.5;
                    flag_y=0;
                }
            }
            if (h.find("(flag c)")!=string::npos)
            {
                if(flagdist>datos.getSeeInst("flag c").getDist())
                {
                    flagdir= this->datos.getSeeInst("flag c").getDir();
                    flagdist=this->datos.getSeeInst("flag c").getDist();
                    flag_x=0;
                    flag_y=0;
                }
            }
        }
        alpha = linedir;
        alpha2 = (linedir - flagdir)*3.141592/180;

        abs_x=flag_x-(flagdist*(cos(alpha2)));
        abs_y=flag_y+(flagdist*(sin(alpha2)));

        posicion.setX(abs_x);
        posicion.setY(abs_y);
        if (linedist<2)
            cercaLinea = true;
    }
}

/**
 * @brief Jugador::getPosicion
 * @return Devuelve la posición del jugador.
 */
Punto Jugador::getPosicion()
{
    return posicion;
}

/**
 * @brief Jugador::goTo Función para mover nuestro jugador a cualquier punto del campo que queramos.
 * @param p Variable de tipo PUNTO donde asignamos la posición de destino.
 *
 * Esta función nos permite llevar a nuestro jugador a cualquier punto del campo, en ella tenemos
 * en cuenta en todo momento la posición de la pelota y si nos la encontramos de camino dejamos
 * de ir a nuestro destino y salimos de la función para ir hacia la pelota.
 */
void Jugador::goTo(Punto p)
{
    double dist,angle,rel_x,rel_y,alpha2,rel_angle, ciclo;
    ciclo = datos.getCiclo();
    /** Posición relativa a nosotros*/
    rel_x= p.getX() -posicion.getX();
    rel_y= p.getY() -posicion.getY();

    /** Distancia relativa a nosotros*/
    dist=sqrt((rel_x*rel_x)+(rel_y*rel_y));
    /** Vamos a la posición deseada mientras no tengamos la pelota cerca */

    angle = acos(rel_x/dist)*180/3.141592;

    if (rel_y>0)
        angle = 360 - angle;

    rel_angle=angle-alpha2;

    if (rel_angle<0)
        rel_angle=360+rel_angle;

    girar(rel_angle);

    while(dist>2 && datos.getCiclo()-ciclo < 100)
    {
        if ((veoPelota==true && datos.getSeeInst("ball").getDist()<10)|| datos.hearEvent==true)
        {
            break;
        }
        else
        {
            alpha2=alpha;

            /** Posición relativa a nosotros*/
            rel_x= p.getX() - posicion.getX();
            rel_y= p.getY() - posicion.getY();

            /** Distancia relativa a nosotros*/
            dist=sqrt((rel_x*rel_x)+(rel_y*rel_y));

            /** Angulo relativo a nosotros en grados*/

            angle = acos(rel_x/dist)*180/3.141592;
            if (rel_y>0)
                angle = 360 - angle;

            rel_angle=angle-alpha2;
            if (rel_angle<0)
                rel_angle=360+rel_angle;

            // cout<<"x= "<<posicion.getX()<<" , y= "<<posicion.getY()<< " ,alpha= "<<alpha<<endl;
            // cout<<"angle= "<<angle<< " , dist= "<<dist <<" , rel_x= "<<rel_x<< " , rel_y= "<<rel_y<<endl;
            // cout<<"angulo relativo = "<< rel_angle <<endl;

            if (cercaLinea || posicion.getX()< -60 || posicion.getX()>60 || posicion.getY()<-50 || posicion.getY()>50)
            {
                //girar(45);
                //buscarPelota();
                //usleep(15000);
                cercaLinea = false;
                break;
            }


            if (rel_angle< 355 && rel_angle > 5)
            {
                if (rel_angle <=180)
                {
                    girar(-5);
                    usleep(15000);
                    // mover(80);
                    // usleep(15000);

                }
                if (rel_angle >180)
                {
                    girar(5);
                    usleep(15000);
                    //mover(80);
                    //usleep(15000);

                }
            }
            else
            {
                mover(80);
                //cout<<"me muevo"<<endl;
                usleep(15000);

            }

        }
    }
    cout<<"He llegado"<<endl;
    mover(0);
    usleep(15000);
    buscarPelota();
}


/**
 * @brief Jugador::goTo Función para mover nuestro jugador a cualquier punto del campo que queramos.
 * @param x Coordenada X de la posición de destino.
 * @param y Coordenada Y de la posición de destino.
 *
 * Esta función nos permite llevar a nuestro jugador a cualquier punto del campo, en ella tenemos
 * en cuenta en todo momento la posición de la pelota y si nos la encontramos de camino dejamos
 * de ir a nuestro destino y salimos de la función para ir hacia la pelota.
 */
void Jugador::goTo(double x, double y)
{
    double dist,angle,rel_x,rel_y,alpha2,rel_angle, ciclo;
    ciclo = datos.getCiclo();
    /** Posición relativa a nosotros*/
    rel_x= x -posicion.getX();
    rel_y= y -posicion.getY();

    /** Distancia relativa a nosotros*/
    dist=sqrt((rel_x*rel_x)+(rel_y*rel_y));
    /** Vamos a la posición deseada mientras no tengamos la pelota cerca */

    angle = acos(rel_x/dist)*180/3.141592;

    if (rel_y>0)
        angle = 360 - angle;

    rel_angle=angle-alpha2;

    if (rel_angle<0)
        rel_angle=360+rel_angle;

    girar(rel_angle);

    while(dist>2 && datos.getCiclo()-ciclo < 100)
    {
        if ((veoPelota==true && datos.getSeeInst("ball").getDist()<10) || datos.hearEvent==true)
        {
            break;
        }
        else
        {
            alpha2=alpha;

            /** Posición relativa a nosotros*/
            rel_x= x - posicion.getX();
            rel_y= y - posicion.getY();

            /** Distancia relativa a nosotros*/
            dist=sqrt((rel_x*rel_x)+(rel_y*rel_y));

            /** Angulo relativo a nosotros en grados*/

            angle = acos(rel_x/dist)*180/3.141592;
            if (rel_y>0)
                angle = 360 - angle;

            rel_angle=angle-alpha2;
            if (rel_angle<0)
                rel_angle=360+rel_angle;

            // cout<<"x= "<<posicion.getX()<<" , y= "<<posicion.getY()<< " ,alpha= "<<alpha<<endl;
            // cout<<"angle= "<<angle<< " , dist= "<<dist <<" , rel_x= "<<rel_x<< " , rel_y= "<<rel_y<<endl;
            // cout<<"angulo relativo = "<< rel_angle <<endl;

            if (cercaLinea)
            {
                //girar(45);
                //usleep(15000);
                cercaLinea = false;
                break;
            }



            if (rel_angle< 355 && rel_angle > 5)
            {
                if (rel_angle <=180)
                {
                    girar(-5);
                    usleep(15000);
                    //mover(80);
                    //usleep(15000);

                }
                if (rel_angle >180)
                {
                    girar(5);
                    usleep(15000);
                    //mover(80);
                    //usleep(15000);

                }
            }
            else
            {
                mover(80);
                //cout<<"me muevo"<<endl;
                usleep(15000);

            }
        }
    }
    mover(0);
    usleep(15000);
    buscarPelota();
}

/**
 * @brief Jugador::hearReferee Función que interpreta los mensajes del árbitro.
 *
 * Con esta función devolvemos un numero entero según sea la accion indicada por el arbitro. Este
 * numero lo utilizaremos despues para colocar a los jugadores según sea necesario.
 */
void Jugador::hearReferee()
{
    bool mySide;
    string instruction;
    if ((datos.hearEvent == true) && (datos.getultimaCadena().find("referee")!=string::npos ||
                                      datos.getultimaCadena().find("goal") != string::npos ||
                                      datos.getultimaCadena().find("play_on") != string::npos))
    {
        //cout<<datos.getultimaCadena()<<endl;
        instruction = datos.getHearInst("referee").getinstruction();
        if (datos.getSide() == datos.getHearInst("referee").getside())
            mySide = true;
        else
            mySide = false;

        if(instruction == "play_on")
            refereeMode = 0;

        if (instruction == "kick_off")
        {
            if (mySide)
                refereeMode = 1;  //1 si saca de centro nuestro equipo
            else
                refereeMode = 2;  //2 si saca de centro el equipo contrario

        }

        if (instruction == "kick_in")
        {
            if (mySide)
                refereeMode = 3; //3 si saca de banda nuestro equipo
            else
                refereeMode = 4; //4 si saca de banda el equipo contrario
        }

        if (instruction == "free_kick")
        {
            if(mySide)
                refereeMode = 5; //5 si saca la falta mi equipo
            else
                refereeMode = 6; //6 si saca la falta el quipo contrario
        }

        if (instruction == "corner_kick")
        {
            if(mySide)
                refereeMode = 7; //7 si saca de corner mi equipo
            else
                refereeMode = 8; //8 si saca el corner el equio contrario
        }

        if (instruction == "goal_kick")
        {
            if (mySide)
                refereeMode = 9; //9 Si saca de porteria mi equipo
            else
                refereeMode = 10; //10 si saca de porteria el equipo contrario
        }

        if (instruction == "before_kick_off")
            refereeMode = 11; //11 si estamos en before_kick_off

        if (instruction == "offside")
        {
            if (mySide)
                refereeMode = 12; //12 si el fuera de juego es del otro equipo
            else
                refereeMode = 13; //13 si el fuera de juego es de mi equipo
        }

        if(instruction == "half_time")
        {
            if (datos.getSide() == "l")
                datos.setSide("r");
            else
                datos.setSide("l");
            refereeMode = 14; //14 despues de cambiar el lado de juego en el descanso
        }
    }
}

bool Jugador::distanciaJugadoresPropios(float distancia)
{
    for (int i = 0; i < 12; i++)
    {
        if(datos.getJugadorPropio(i).getDist() > distancia);
        else
            return false;
    }
    return true;
}

bool Jugador::jugadorPropioCercaBalon()
{
    bool aux = true;
    float miDistancia,suDistancia;
    float pelotaX = posicionPelota().getX();
    float pelotaY = posicionPelota().getY();
    miDistancia = sqrt(pow(posicion.getX()-pelotaX,2)+pow(posicion.getY()-pelotaY,2));
    for(int i = 1; i < 12; i++)
    {
        float x = posicionJugadorPropio(i).getX();
        float y = posicionJugadorPropio(i).getY();
        suDistancia = sqrt(pow(x-pelotaX,2)+pow(y-pelotaY,2));
        if(miDistancia < suDistancia)
            aux = false;
    }
    return aux;

}

bool Jugador::distanciaJugadoresContrarios(float distancia)
{
    for (int i = 0; i < 12; i++)
    {
        if(datos.getJugadorContrario(i).getDist() > distancia);
        else
            return false;
    }
    return true;
}
Punto Jugador::posicionJugadorPropio(int dorsal)
 {
    double x,y,angle;
    Punto pos;
    angle = alpha - datos.getJugadorPropio(dorsal).getDir() ;
    x = posicion.getX()+ (datos.getJugadorPropio(dorsal).getDist()*cos(angle));
    y = posicion.getY()+ (datos.getJugadorPropio(dorsal).getDist()*sin(angle));
    pos.setX(x);
    pos.setY(y);
    return pos;

 }
